package ynu.edu.controller;

import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
import ynu.edu.entity.User;
import ynu.edu.feign.ServiceProviderService;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * 熔断器测试控制器
 * 分别使用熔断器A和熔断器B进行容错保护
 */
@RestController
@RequestMapping("/circuitbreaker")
public class CircuitBreakerTestController {

    @Resource
    private ServiceProviderService serviceProviderService;

    /**
     * 测试熔断器A - 获取用户信息
     * 配置: 失败率30%, 时间窗口10秒, 最小请求5个
     */
    @GetMapping("/testCircuitBreakerA/{userId}")
    @CircuitBreaker(name = "circuitBreakerA", fallbackMethod = "getUserByIdFallback")
    public Map<String, Object> testCircuitBreakerA(@PathVariable("userId") Integer userId) {
        // 直接调用远程服务
        User user = serviceProviderService.GetUserById(userId);
        System.out.println("远程服务调用成功，返回用户: " + user.getUserName() + " from " + user.getPassWord());
        
        return Map.of(
                "circuitBreaker", "circuitBreakerA",
                "status", "SUCCESS",
                "httpStatus", 200,
                "data", user,
                "timestamp", LocalDateTime.now(),
                "message", "熔断器A - 正常调用成功",
                "userId", userId
        );
    }

    /**
     * 熔断器A的降级方法
     */
    public Map<String, Object> getUserByIdFallback(Integer userId, Exception ex) {
        System.out.println("熔断器A降级: " + ex.getMessage());
        
        return Map.of(
                "circuitBreaker", "circuitBreakerA",
                "status", "FALLBACK",
                "httpStatus", 200,
                "userId", userId,
                "timestamp", LocalDateTime.now(),
                "error", ex.getMessage(),
                "message", "熔断器A已触发 - 服务降级响应",
                "fallbackData", Map.of(
                        "userId", userId,
                        "userName", "降级用户-" + userId,
                        "passWord", "fallback123"
                )
        );
    }

    /**
     * 测试熔断器B - 获取所有用户列表
     * 配置: 失败率50%, 慢调用30%, 时间窗口10秒, 最小请求5个
     */
    @GetMapping("/testCircuitBreakerB")
    @CircuitBreaker(name = "circuitBreakerB", fallbackMethod = "getAllUsersFallback")
    public Map<String, Object> testCircuitBreakerB() {
        // 直接调用远程服务
        Map<String, Object> users = serviceProviderService.getAllUsers();
        System.out.println("远程服务调用成功，获取所有用户列表");
        
        return Map.of(
                "circuitBreaker", "circuitBreakerB",
                "status", "SUCCESS",
                "httpStatus", 200,
                "data", users,
                "timestamp", LocalDateTime.now(),
                "message", "熔断器B - 正常调用成功"
        );
    }

    /**
     * 熔断器B的降级方法
     */
    public Map<String, Object> getAllUsersFallback(Exception ex) {
        System.out.println("熔断器B降级: " + ex.getMessage());
        
        return Map.of(
                "circuitBreaker", "circuitBreakerB", 
                "status", "FALLBACK",
                "httpStatus", 200,
                "timestamp", LocalDateTime.now(),
                "error", ex.getMessage(),
                "message", "熔断器B已触发 - 服务降级响应",
                "fallbackData", Map.of(
                        "users", java.util.List.of(
                                Map.of("userId", 1, "userName", "降级用户1", "passWord", "fallback123"),
                                Map.of("userId", 2, "userName", "降级用户2", "passWord", "fallback123")
                        ),
                        "total", 2,
                        "message", "这是降级数据，来自熔断器B"
                )
        );
    }

    /**
     * 批量测试熔断器A - 快速触发熔断
     */
    @GetMapping("/batchTestA/{userId}")
    public Map<String, Object> batchTestCircuitBreakerA(@PathVariable("userId") Integer userId) {
        java.util.List<Map<String, Object>> results = new java.util.ArrayList<>();
        int successCount = 0;
        int fallbackCount = 0;

        // 连续调用10次，观察熔断器效果
        for (int i = 0; i < 10; i++) {
            try {
                Map<String, Object> result = testCircuitBreakerA(userId);
                results.add(Map.of("attempt", i + 1, "result", result));
                if ("SUCCESS".equals(result.get("status"))) {
                    successCount++;
                } else {
                    fallbackCount++;
                }
            } catch (Exception e) {
                results.add(Map.of("attempt", i + 1, "error", e.getMessage()));
                fallbackCount++;
            }
            
            // 每次调用间隔500ms
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }

        return Map.of(
                "testType", "熔断器A批量测试",
                "totalAttempts", 10,
                "successCount", successCount,
                "fallbackCount", fallbackCount,
                "results", results,
                "explanation", "观察熔断器A的状态变化：CLOSED -> OPEN -> HALF_OPEN"
        );
    }

    /**
     * 批量测试熔断器B - 快速触发熔断
     */
    @GetMapping("/batchTestB")
    public Map<String, Object> batchTestCircuitBreakerB() {
        java.util.List<Map<String, Object>> results = new java.util.ArrayList<>();
        int successCount = 0;
        int fallbackCount = 0;

        // 连续调用10次，观察熔断器效果
        for (int i = 0; i < 10; i++) {
            try {
                Map<String, Object> result = testCircuitBreakerB();
                results.add(Map.of("attempt", i + 1, "result", result));
                if ("SUCCESS".equals(result.get("status"))) {
                    successCount++;
                } else {
                    fallbackCount++;
                }
            } catch (Exception e) {
                results.add(Map.of("attempt", i + 1, "error", e.getMessage()));
                fallbackCount++;
            }
            
            // 每次调用间隔500ms
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }

        return Map.of(
                "testType", "熔断器B批量测试",
                "totalAttempts", 10,
                "successCount", successCount,
                "fallbackCount", fallbackCount,
                "results", results,
                "explanation", "观察熔断器B的状态变化：失败率+慢调用双重保护"
        );
    }
} 